﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Api.DI
{
    public class DI_Run_Params
    {
        /// <summary>
        /// 注入类型 0 Singleton 1 Scoped 2 Transient
        /// </summary>
        public int DI_Type { get; set; }
        /// <summary>
        /// 方法组名称
        /// </summary>
        public string[] T_Names { get; set; }
    }
    /// <summary>
    /// DI的反射注入方法
    /// </summary>
    public class Run_Service
    {
        /// <summary>
        ///  注入指定方法集中的方法类
        /// </summary>
        /// <param name="Configuration"></param>
        /// <param name="services"></param>
        public static void DI_Run(IConfiguration Configuration, IServiceCollection services)
        {

            Assembly assembly = Assembly.Load(new AssemblyName(Configuration["DI:AssemblyName"]));
            string TypesName = Configuration["DI:TypesName"].ToString();
            List<DI_Run_Params> DI_Params = new List<DI_Run_Params>();
            //注入Singleton
            var Singleton = Configuration.GetSection("DI").GetSection("Singleton_Types").GetChildren().ToArray().Select(c => c.Value).ToArray();
            DI_Params.Add(new DI_Run_Params() { DI_Type = 0, T_Names = Singleton });
            //注入Scoped
            var Scoped = Configuration.GetSection("DI").GetSection("Scoped_Types").GetChildren().ToArray().Select(c => c.Value).ToArray();
            DI_Params.Add(new DI_Run_Params() { DI_Type = 1, T_Names = Scoped });
            //注入
            var Transient = Configuration.GetSection("DI").GetSection("Transient_Types").GetChildren().ToArray().Select(c => c.Value).ToArray();
            DI_Params.Add(new DI_Run_Params() { DI_Type = 2, T_Names = Transient });
            //注入对应节点数据
            DI_Run_Section(services, DI_Params, assembly, TypesName);
        } 
        /// <summary>
        /// 注入节点
        /// </summary>
        /// <param name="services"></param>
        /// <param name="DI_Params"></param>
        /// <param name="assembly"></param>
        /// <param name="TypesName"></param>
        private static void DI_Run_Section(IServiceCollection services, List<DI_Run_Params> DI_Params, Assembly assembly, string TypesName)
        {
            foreach (var Pitem in DI_Params)
            {
                foreach (var item in Pitem.T_Names)
                {
                    Type t = assembly.GetType(TypesName + item);
                    var interfaceType = t.GetInterfaces();
                    if (!t.IsGenericType)
                    {
                        foreach (var Iitem in interfaceType)
                        {
                            switch (Pitem.DI_Type)
                            {
                                case 0:
                                    services.AddSingleton(Iitem, t);
                                    break;
                                case 1:
                                    services.AddScoped(Iitem, t);
                                    break;
                                case 2:
                                    services.AddTransient(Iitem, t);
                                    break;
                            }
                        }
                    };
                }
            }
        }
    }
}
